home *** CD-ROM | disk | FTP | other *** search
- /* CB3.C - C Beautifier - Jim Kyle (76703,762) - 05/06/86
- * not mainstream rules, but I like 'em!!
- */
-
- /* port to Apollo Domain by Jinfu Chen (72327,2434) - 03/07/87 */
- /* port to Atari ST by Jinfu Chen - 03/08/87 */
-
- /*#define CPM / remove for MSDOS, include for CPM */
- /*#define APOLL O / remove for Apollo Domain version */
- #define Megamax
-
- /* ------------ *
- * header files *
- * ------------ */
- #ifdef CPM
- #include "libc.h" /* specifically, Aztec Cii V1.05c */
- #include "ctype.h"
- #else
- #ifdef MSDOS
- #include "stdio.h" /* specifically, CI's C86 V1.33 */
- #define ishex(x) isdigit(x) || ( toupper(x) < 'G' && toupper(x) >= 'A')
- #else
- #ifdef APOLLO /* specifically, Domain C Rev 4.16 */
- #include <ctype.h>
- #include <stdio.h>
- #define ishex(x) isdigit(x) || ( toupper(x) < 'G' && toupper(x) >= 'A')
- #else
- #ifdef Megamax /* specifically, Megamax C Rev 1.1 */
- #include <ctype.h>
- #include <stdio.h>
- #include <osbind.h>
- #define ishex(x) isdigit(x) || ( toupper(x) < 'G' && toupper(x) >= 'A')
- #endif
-
- #endif
-
- /* ------------------ *
- * symbolic constants *
- * ------------------ */
- #define LINEW 78
- #define CMNTCOL 40
- #define MTAB 8
- #define LIND 2
- #define YES 1
- #define NO 0
-
- /* ---------------- *
- * global variables *
- * ---------------- */
- char bfr [ 128 ];
- FILE * inf, * otf;
- int clvl = 0,
- plvl = 1,
- ilvl = 0,
- ppilv = 0,
- istk [ 64 ],
- istkp = 0,
- indf = 0,
- cflg = 0,
- dflg = 0,
- iflg = 0,
- tok = 0,
- oldtok = 0,
- mtabv = MTAB,
- lnwv = LINEW,
- lindv = LIND,
- ccv = CMNTCOL,
- nval = 0,
- ln = 1,
- col = 0;
-
- main ( argc, argv ) int argc ;
- char * argv [];
- { if ( argc == 1 || * argv [ 1 ] == '?' )/* help summary */
- { msg ( "\nCommand syntax is: CB [[<args>] [<file>]] <CR>\n" );
- msg ( " where <args> begins with '-' and is followed by\n" );
- msg ( "\tCn - start comments at col n\n" );
- msg ( "\tIn - each indent is n spaces\n" );
- msg ( "\tNn - line number with increment n\n" );
- msg ( "\tO<file> - output to <file> (must be last)\n" );
- msg ( "\tTn - machine tabs are n cols apart\n" );
- msg ( "\tWn - line length is n cols\n" );
- msg ( "\tAny mix of args can follow the '-'; each one\n" );
- msg ( "\t takes effect immediately.\n" );
- msg ( " <file> is a full filespec; <CR> is RETURN or ENTER.\n" );
- msg ( " The [ and ] indicate options; don't type them.\n\n" );
- msg ( "Default values of the settings are:\n" );
- msg ( "\tC40 I2 N0 T8 W78\n" );
- exit ( 0 );
- }
- otf = stdout;
- while ( -- argc ) /* let parsearg() do most */
- parsearg ( *++ argv );
- }
-
- char * dmpdgt ( fn ) /* skip over digits */
- char * fn;
- { if ( isdigit ( * fn ))
- { while ( isdigit ( * fn ))
- ++ fn;
- -- fn;
- }
- return ( fn );
- }
-
- parsearg ( fn ) /* process one arg */
- char * fn;
- { if ( * fn == '-' ) /* is an argument */
- while ( *++ fn )
- { switch ( toupper ( * fn ))
- {
- case 'C' :
- ccv = atoi ( ++ fn ); /* set comment column */
- fn = dmpdgt ( fn );
- break;
-
- case 'I' :
- lindv = atoi ( ++ fn ); /* set indent width */
- if ( lindv < 1 )
- lindv = 1;
- fn = dmpdgt ( fn );
- break;
-
- case 'N' :
- nval = atoi ( ++ fn ); /* set line number increment */
- fn = dmpdgt ( fn );
- break;
-
- case 'O' :
- fclose ( otf ); /* write to file */
- otf = fopen ( ++ fn, "w" );
- msg ( "Writing output to: " );
- msg ( fn );
- tocrt ( '\n' );
- lnwv = 32767; /* never wrap to a file */
- return;
-
- case 'T' :
- mtabv = atoi ( ++ fn ); /* set mach tab spacing */
- if ( mtabv < 1 )
- mtabv = 1000;
- fn = dmpdgt ( fn );
- break;
-
- case 'W' :
- lnwv = atoi ( ++ fn ); /* set line width */
- fn = dmpdgt ( fn );
- if ( lnwv < 1 )
- lnwv = 32767;
- break;
-
- default :
- msg ( "Unknown arg: " );
- tocrt ( * fn );
- tocrt ( '\n' );
- }
- }
- else /* treat as filename */
- {
- if ( nval )
- lnwv -= mtabv;
- dofil ( fn );
- if ( nval )
- lnwv += mtabv;
- }
- }
-
- dofil ( fn ) /* process one file */
- char * fn;
- { int loop ,
- svtok;
- if ( ! ( inf = fopen ( fn, "r" ))) /* open the file */
- { msg ( "can't open " );
- msg ( fn );
- tocrt ( '\n' );
- return;
- }
- col = clvl = oldtok = 0; /* initialize globals */
- ln = 1;
- if ( nval ) /* output line number */
- outf ( ln * nval );
- outb ( '/' ); /* fake out C86 quirk */
- outs ( "* " );
- outs ( fn );
- outs ( " as formatted by CB.C\t*" );
- outb ( '/' );
- nl ();
- for ( loop = 1; loop; oldtok = tok ) /* main loop */
- { tok = gtok ( inf ); /* get next token */
- if ( oldtok == ';'
- && tok != ' '
- && col ) /* break after statement */
- outb ( '\n' );
- switch ( tok ) /* special processing */
- {
- case 0 : /* newline or comment */
- if ( clvl && ! iflg )
- tok = oldtok; /* ignore it outside condx */
- else
- if ( iflg || ! oldtok )
- { nl ();
- if ( iflg )
- ind ( ilvl + 2 );
- tok = ' ';
- }
- continue;
-
- case ' ' : /* blank */
- tok = oldtok;
- continue;
-
- case EOF : /* end of input */
- loop = 0;
- continue;
-
- case '{' : /* begin compound */
- if ( col )
- nl ();
- ind ( ilvl ++ ); /* push ilvl in */
- ++ clvl;
- outs ( bfr );
- tok = ' ';
- continue;
-
- case '}' : /* end compound */
- if ( col )
- nl ();
- if ( ilvl )
- -- ilvl; /* pop ilvl out for c.s. */
- ind ( ilvl );
- outs ( bfr );
- nl ();
- if ( iflg )
- iflg = 0;
- -- clvl;
- popilvl (); /* pop ilvl up if applicable */
- tok = ';';
- continue;
-
- case '(' : /* may be condition start */
- ++ plvl;
- if ( isalnum ( oldtok )
- || isop ( oldtok ))
- outb ( ' ' );
- outs ( bfr );
- tok = '(';
- continue;
-
- case ')' : /* may be condition end */
- -- plvl;
- if ( isalnum ( oldtok ))
- outb ( ' ' );
- outs ( bfr );
- tok = ')';
- if ( iflg && ( iflg == plvl ))
- { iflg = 0; /* end of condition */
- tok = ';'; /* so fake statement end */
- }
- continue;
-
- case ':' : /* may be end of label */
- outb ( ' ' );
- outs ( bfr );
- tok = ':';
- if ( cflg ) /* case or default label */
- { tok = ';'; /* will force \n after comments */
- ++ ilvl;
- cflg = 0;
- }
- continue;
-
- case ';' : /* may be end of statement */
- ind ( ilvl );
- outs ( bfr );
- if ( iflg && ( plvl != iflg ))
- outb ( ' ' ); /* inside "for" condition */
- else /* not in a "for" */
- popilvl (); /* pop back up if ready */
- dflg = 0;
- continue;
-
- case ',' : /* list separator */
- outs ( bfr );
- if ( dflg ) /* inside a declaration list */
- outb ( '\n' ), ind ( 2 );
- else /* elsewhere */
- outb ( ' ' );
- continue;
-
- case '#' : /* preprocessor flag */
- /* if ( col ) /* shouldn't happen */
- /* outs ( bfr ); */
- /* else /* handle preprocessor line */
- dopp ( inf );
- continue;
-
- case 'A' : /* keyword or identifier */
- if ( indf )
- { nl ();
- tok = 'A';
- indf = 0;
- }
-
- case '0' : /* numeric string */
-
- case 'C' : /* char constant */
-
- case 'S' : /* string constant */
- svtok = tok;
- if (( tok == 'A' )
- && kwd ()
- && ( ! dflg )
- && ( col > ( ppilv + ilvl ) * lindv ))
- nl ();
- if ( oldtok && ( oldtok != ' ' ))
- outb ( ' ' );
- break;
-
- default : /* operators, etc. */
- if ( tok & 128 )
- { outb ( tok ); /* escaped chars ignored */
- tok = svtok;
- continue;
- }
- svtok = tok;
- if ( isop ( svtok ) && ! isop ( oldtok ))
- outb ( ' ' );
- break;
- }
- ind ( ilvl );
- if ( indf ) /* push ilvl in */
- { istk [ ++ istkp ] = (( ilvl ++ ) << 8 ) | ( clvl & 255 );
- if ( iflg )
- indf = 0;
- }
- if ( isalnum ( oldtok )
- && ! ( isalnum ( svtok )
- || isop ( svtok )))
- outb ( ' ' );
- outs ( bfr );
- tok = svtok;
- if ( tok == oldtok )
- outb ( ' ' );
- }
- nl ();
- outb ( '/' ); /* trailer comment */
- outs ( "* end of " );
- outs ( fn );
- outs ( " *" );
- outb ( '/' );
- nl ();
- }
-
- poll () /* break or pause */
- #ifdef CPM
- { int c ;
- if (( c = bdos ( 6, 255 )) == 3 ) /* check for BREAK */
- exit ( 7 );
- if ( c ) /* check for PAUSE */
- { msg ( "<<PAUSED>>" );
- while ( bdos ( 6, 255 ) != ' ' )
- ; /* wait for SPACE */
- msg ( "\b\b\b\b\b\b\b\b\b\b" );
- }
- }
- #else
- { /* empty for MSDOS */
- }
- #endif
-
- dopp ( fd ) /* handle preprocessor lines */
- FILE * fd;
- { int asmflg;
- tok = gtok ( fd );
- if ( tok == 'A' ) /* keyword at start of line */
- { if ( ! strcmp ( bfr, "asm" ))
- { if ( col )
- nl ();
- asmflg = 0;
- /* ind ( 0 ); */
- outb ( '#' );
- outs ( bfr );
- do /* just echo until #endasm */
- {
- tok = getc ( fd );
- outb ( tok );
- switch ( tok )
- { case '#':
- if (asmflg == 0)
- ++asmflg;
- else
- asmflg = 0;
- break;
- case 'e':
- if (asmflg == 1)
- ++asmflg;
- else
- asmflg = 0;
- break;
- case 'n':
- if (asmflg == 2)
- ++asmflg;
- else
- asmflg = 0;
- break;
- case 'd':
- if (asmflg == 3)
- ++asmflg;
- else
- asmflg = 0;
- break;
- case 'a':
- if (asmflg == 4)
- ++asmflg;
- else
- asmflg = 0;
- break;
- case 's':
- if (asmflg == 5)
- ++asmflg;
- else
- asmflg = 0;
- break;
- case 'm':
- if (asmflg == 6)
- ++asmflg;
- else
- asmflg = 0;
- break;
- default:
- asmflg = 0;
- }
- }
- while ( asmflg != 7 )
- ;
- }
- else
- if ( bfr [ 0 ] == 'i' && bfr [ 1 ] == 'f' )
- { ppkw ( 0 );
- ppilv ++ ;
- }
- else
- if ( ! strcmp ( bfr, "else" ))
- ppkw ( - 1 );
- else
- if ( ! strcmp ( bfr, "endif" ))
- { -- ppilv;
- ppkw ( 0 );
- }
- else /* all other keywords */
- ppkw ( 0 );
- }
- else /* no keyword after the '#' */
- ppkw ( 0 );
- while ( tok = gtok ( fd )) /* process rest of line here */
- outs ( bfr ); /* output without change */
- nl ();
- tok = 0; /* tell main scanner it was a newline */
- }
-
- ppkw ( n ) /* indent preprocessor line */
- int n ;
- { if ( col ) /* force newline if needed */
- nl ();
- /* ind ( n ); /* only to preprocessor level */
- outb ( '#' ); /* output the '#' */
- outs ( bfr ); /* output the keyword */
- }
-
- gtok ( fd ) /* input scanner */
- FILE * fd;
- { int c ;
- char * p;
- poll (); /* check for pause or break */
- p = bfr;
- * p ++ = c = esc ( fd ); /* save char in buffer */
- * p = 0;
- if ( c == '\n' ) /* newline */
- return ( 0 );
- if ( isspace ( c ) || c == '\r' ) /* whitespace */
- return ( ' ' );
- if ( c < ' ' ) /* any other control char */
- return ( EOF );
- if ( c == '/' ) /* comment? */
- { if (( c = esc ( fd )) != '*' )
- { ungetc ( c, fd ); /* nope */
- c = '/';
- }
- else /* yep, echo it all */
- {
- if ( col )
- ind ( ccv / lindv );
- outb ( '/' );
- outb ( '*' );
- while ( 1 )
- { while (( c = esc ( fd )) != '*' )
- outb ( c );
- outb ( '*' );
- if (( c = esc ( fd )) == '/' )
- { outb ( '/' );
- return ( oldtok != ';' ? 0 : ' ' );
- }
- else
- outb ( c );
- }
- }
- }
- if ( isalpha ( c ) || c == '_' ) /* keyword or identifier */
- { while ( c = esc ( fd ), isalnum ( c )
- || c == '_' )
- * p ++ = c;
- * p = 0;
- ungetc ( c, fd );
- return ( 'A' );
- }
- if ( isdigit ( c )) /* numeric constant */
- { if ( c == '0' ) /* octal or hex */
- { c = esc ( fd ); /* check flag char */
- if ( toupper ( c ) != 'X' ) /* then was not hex */
- ungetc ( c, fd ); /* put it back */
- else
- { *
- p ++ = c; /* save hex flag */
- while ( c = esc ( fd ), ishex ( c ))
- * p ++ = c;
- * p = 0;
- ungetc ( c, fd );
- return ( '0' ); /* and get out */
- }
- }
- while ( c = esc ( fd ), isdigit ( c ))
- * p ++ = c;
- * p = 0;
- ungetc ( c, fd );
- return ( '0' );
- }
- if ( c == '\"' ) /* string constant */
- { while ( c = esc ( fd ), c != '\"' )
- * p ++ = c;
- * p ++ = c;
- * p = 0;
- return ( 'S' );
- }
- if ( c == '\'' ) /* char constant */
- { while ( c = esc ( fd ), c != '\'' )
- * p ++ = c;
- * p ++ = c;
- * p = 0;
- return ( 'C' );
- }
- * p = 0; /* anything else */
- return ( c );
- }
-
- outs ( s ) /* output string */
- char * s;
- { if ( col + strlen ( s ) > lnwv )
- outb ( 128 + '\n' );
- while ( * s )
- outb ( * s ++ );
- }
-
- outb ( c ) /* output byte */
- char c ;
- { if ( c & 128 ) /* ESC sequence */
- { outb ( '\\' );
- c &= 127;
- }
- switch ( c ) /* special treatment */
- {
- case '\t' : /* machine tab */
- col = nxtb ( col );
- tok = ' ';
- out ( c );
- c = 0;
- break;
-
- case '\n' : /* newline */
- ln += 1;
- out ( c );
- if ( nval ) /* line number */
- outf ( ln * nval );
-
- case '\r' : /* CR */
- c = col = 0;
- break;
-
- case ' ' : /* blank */
- tok = ' ';
-
- default : /* anything else */
- if ( c >= ' ' ) /* printable */
- { if ( ++ col > lnwv ) /* check for wrap */
- { col = 0;
- outb ( 128 + '\n' ); /* force cont line */
- }
- }
- else /* control, skip it */
- c = 0;
- break;
- }
- if ( c )
- out ( c ); /* send char out */
- }
-
- out ( c ) /*byte output*/
- char c ;
- { poll ();
- fprintf ( otf, "%c", c );
- }
-
- outf ( n ) /*line number output*/
- int n ;
- { fprintf ( otf, "%d\t", n );
- }
-
- msg ( s ) /* output string to CRT */
- char * s;
- { poll ();
- while ( * s )
- tocrt ( * s ++ );
- }
-
- tocrt ( c ) /* output char to CRT */
- char c ;
- #ifdef CPM
- { if ( c == '\n' )
- bdos ( 6, 13 );
- bdos ( 6, c & 255 ); /* use BDOS for CPM */
- }
- #else
- { fputc ( c, stderr ); /* use DOS for MSDOS */
- }
- #endif
-
- nl () /* newline */
- { outb ( '\n' );
- tok = 0;
- }
-
- ind ( n ) /* do indenting */
- int n ;
- { int svtok ;
- svtok = tok; /* save "tok" past the indent */
- n += ppilv; /* include preprocessor indent */
- n *= lindv;
- while ( nxtb ( col ) <= n ) /* machine tab if possible */
- outb ( '\t' );
- while ( col < n ) /* then fill with spaces */
- outb ( ' ' );
- tok = svtok; /* restore "tok" */
- }
-
- nxtb ( n ) /* return next tabstop */
- int n ;
- { return ( n + ( mtabv - n % mtabv ));
- }
-
- int inchr = '\n'; /* last input character */
-
- esc ( fd ) /* handle ESC chars */
- FILE * fd;
- { if ( inchr == '\n' ) /* if at start of line */
- { inchr = getc ( fd );
- if ( isdigit ( inchr ))
- { while ( inchr = getc ( fd ), isdigit ( inchr ))
- ; /* smash line numbers */
- while ( isspace ( inchr ))
- inchr = getc ( fd ); /* and trailing whitespace */
- }
- }
- else
- inchr = getc ( fd ); /* get next input char */
- if ( inchr != '\\' )
- return ( inchr ); /* normal char */
- return ( inchr = ( getc ( fd ) | 128 ));/* ESC, flag next */
- }
-
- popilvl () /* pop ilvl out */
- { while ( clvl == ( istk [ istkp ] & 255 ))
- { ilvl = 255 & ( istk [ istkp -- ] >> 8 );
- if ( istkp < 0 )
- { istkp = 0;
- return;
- }
- }
- }
-
- kwd () /* check for keyword */
- { if ( ! ( strcmp ( bfr, "break" ))
- || ! ( strcmp ( bfr, "continue" ))
- || ! ( strcmp ( bfr, "return" )))
- return ( YES ); /* ordinary keywords */
- if ( ! ( strcmp ( bfr, "case" ))
- || ! ( strcmp ( bfr, "default" )))
- { outb ( '\n' );
- ++ cflg;
- -- ilvl;
- return ( YES ); /* only inside switch() */
- }
- if ( ! ( strcmp ( bfr, "char" ))
- || ! ( strcmp ( bfr, "double" ))
- || ! ( strcmp ( bfr, "extern" ))
- || ! ( strcmp ( bfr, "float" ))
- || ! ( strcmp ( bfr, "int" ))
- || ! ( strcmp ( bfr, "static" )))
- { ++ dflg;
- return ( YES ); /* declarations */
- }
- if ( ! ( strcmp ( bfr, "do" ))
- || ! ( strcmp ( bfr, "else" )))
- { ++ indf;
- return ( YES ); /* indent but no parens */
- }
- if ( ! ( strcmp ( bfr, "for" ))
- || ! ( strcmp ( bfr, "if" ))
- || ! ( strcmp ( bfr, "switch" ))
- || ! ( strcmp ( bfr, "while" )))
- { iflg = plvl;
- ++ indf;
- return ( YES ); /* indent with parens */
- }
- return ( NO ); /* not a keyword */
- }
-
- isop ( t ) /* return YES if t is operator */
- int t ;
- { if (( ! oldtok ) || oldtok == ' ' )
- return ( NO ); /* force NO if first nonblank */
- return ( index ( "+-/!*^?~=<>&|", t ) ? YES : NO );
- }
-
- /* end of CB3.C */
-